/*            Copyright(c) 2006-2008 Dave Sexton           *
 * http://www.codeplex.com/DocProject                      *
 * http://www.codeplex.com/DocProject/Project/License.aspx *
 ***********************************************************/
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using DaveSexton.DocProject.Sandcastle.TopicManagement;

namespace DaveSexton.DocProject.Sandcastle.ContentManagement
{
	internal sealed class DataGridViewContentItemCell : DataGridViewTextBoxCell
	{
		#region Public Properties
		public override Type EditType
		{
			get
			{
				return defaultEditType;
			}
		}
		#endregion

		#region Private / Protected
		private static readonly Type defaultEditType = typeof(ContentItemEditorControl);
		#endregion

		#region Constructors
		/// <summary>
		/// Constructs a new instance of the <see cref="DataGridViewContentItemCell" /> class.
		/// </summary>
		public DataGridViewContentItemCell()
		{
		}
		#endregion

		#region Methods
		protected override object GetValue(int rowIndex)
		{
			if (rowIndex == -1)
				return base.GetValue(rowIndex);
			else
			{
				ContentItemAttributeData attribute = (ContentItemAttributeData) DataGridView.Rows[rowIndex].DataBoundItem;
				TopicSectionAttributeType attributeType = (attribute == null) ? TopicSectionAttributeType.String : attribute.AttributeType;

				switch (attributeType)
				{
					case TopicSectionAttributeType.Boolean:
						return (string.IsNullOrEmpty(attribute.Value)) ? "False" : attribute.Value.ToString();
					default:
						return base.GetValue(rowIndex);
				}
			}
		}

		public override void InitializeEditingControl(int rowIndex, object initialFormattedValue, DataGridViewCellStyle dataGridViewCellStyle)
		{
			base.InitializeEditingControl(rowIndex, initialFormattedValue, dataGridViewCellStyle);

			ContentItemEditorControl control = (ContentItemEditorControl) DataGridView.EditingControl;
			control.Value = (string) initialFormattedValue;
		}
		#endregion

		#region Nested
		private sealed class ContentItemEditorControl : Control, IDataGridViewEditingControl
		{
			#region Public Properties
			public string Value
			{
				get
				{
					return _value;
				}
				set
				{
					_value = value;
				}
			}
			#endregion

			#region Private / Protected
			private readonly ComboBox comboBox = new ComboBox();
			private readonly TextBox textBox = new TextBox();
			private readonly Button button = new Button();
			private TopicSectionAttributeType attributeType;
			private string _value;
			private bool valueChanged;
			private int rowIndex;
			private DataGridView dataGridView;
			#endregion

			#region Constructors
			/// <summary>
			/// Constructs a new instance of the <see cref="ContentItemEditorControl" /> class.
			/// </summary>
			public ContentItemEditorControl()
			{
				TabStop = false;

				textBox.Name = "TextBox";
				textBox.BorderStyle = BorderStyle.None;
				textBox.AutoSize = false;
				textBox.TabStop = false;
				textBox.Dock = DockStyle.Fill;
				textBox.AllowDrop = true;
				textBox.DragOver += new DragEventHandler(textBox_DragOver);
				textBox.TextChanged += textBox_TextChanged;
				textBox.Enter += textBox_Enter;

				comboBox.Name = "ComboBox";
				comboBox.TabStop = false;
				comboBox.DropDownStyle = ComboBoxStyle.DropDownList;
				comboBox.Items.Add("False");
				comboBox.Items.Add("True");
				comboBox.SelectedIndex = 0;
				comboBox.Dock = DockStyle.Fill;
				comboBox.SelectedIndexChanged += comboBox_SelectedIndexChanged;
				
				button.Name = "Button";
				button.TabStop = false;
				button.Text = Resources.Text.Elipses;
				button.AutoSize = true;
				button.AutoSizeMode = AutoSizeMode.GrowAndShrink;
				button.Dock = DockStyle.Right;
				button.Click += new EventHandler(button_Click);
			}
			#endregion

			#region Methods
			private void Initialize(bool selectAll)
			{
				Controls.Clear();

				if (rowIndex > -1)
				{
					ContentItemAttributeData attribute = (ContentItemAttributeData) dataGridView.Rows[rowIndex].DataBoundItem;
					attributeType = (attribute == null) ? TopicSectionAttributeType.String : attribute.AttributeType;

					switch (attributeType)
					{
						case TopicSectionAttributeType.Boolean:
							comboBox.SelectedItem = (string.IsNullOrEmpty(_value)) ? "False" : _value;
							Controls.Add(comboBox);
							break;
						case TopicSectionAttributeType.File:
							textBox.Text = _value;

							if (selectAll)
								textBox.SelectAll();

							Controls.Add(textBox);
							Controls.Add(button);
							break;
						default:
							textBox.Text = _value;

							if (selectAll)
								textBox.SelectAll();

							Controls.Add(textBox);
							break;
					}
				}
			}
			#endregion

			#region Event Handlers
			private void comboBox_SelectedIndexChanged(object sender, EventArgs e)
			{
				_value = comboBox.SelectedText;
				valueChanged = true;
				dataGridView.NotifyCurrentCellDirty(true);
			}

			private void textBox_TextChanged(object sender, EventArgs e)
			{
				_value = textBox.Text;
				valueChanged = true;
				dataGridView.NotifyCurrentCellDirty(true);
			}

			private void textBox_DragOver(object sender, DragEventArgs e)
			{
				e.Effect = DragDropEffects.None;

				if (e.Data.GetDataPresent("Text"))
				{
					if ((e.AllowedEffect & DragDropEffects.Copy) == DragDropEffects.Copy)
						e.Effect = DragDropEffects.Copy;
					else if ((e.AllowedEffect & DragDropEffects.Move) == DragDropEffects.Move)
						e.Effect = DragDropEffects.Move;
				}
			}

			private void textBox_Enter(object sender, EventArgs e)
			{
				textBox.SelectAll();
			}

			private void button_Click(object sender, EventArgs e)
			{
				using (OpenFileDialog dialog = new OpenFileDialog())
				{
					Uri uri;
					if (textBox.TextLength > 0 && Uri.TryCreate(textBox.Text, UriKind.RelativeOrAbsolute, out uri))
					{
						string path = (uri.IsAbsoluteUri) ? uri.LocalPath : uri.ToString();

						dialog.FileName = System.IO.Path.GetFileName(path);
						dialog.InitialDirectory = System.IO.Path.GetDirectoryName(path);
					}

					dialog.Title = "Select File";
					dialog.Filter = "All Files (*.*)|*.*";

					if (dialog.ShowDialog(dataGridView.FindForm()) == DialogResult.OK)
						textBox.Text = dialog.FileName;
				}
			}
			#endregion

			#region IDataGridViewEditingControl Members
			public void ApplyCellStyleToEditingControl(DataGridViewCellStyle dataGridViewCellStyle)
			{
				if (dataGridViewCellStyle == null)
					throw new ArgumentNullException("dataGridViewCellStyle");

				ForeColor = dataGridViewCellStyle.ForeColor;
				BackColor = dataGridViewCellStyle.BackColor;
			}

			public DataGridView EditingControlDataGridView
			{
				get
				{
					return dataGridView;
				}
				set
				{
					dataGridView = value;
				}
			}

			public object EditingControlFormattedValue
			{
				get
				{
					return GetEditingControlFormattedValue(DataGridViewDataErrorContexts.Formatting);
				}
				set
				{
					_value = (value == null) ? null : value.ToString();
				}
			}

			public int EditingControlRowIndex
			{
				get
				{
					return rowIndex;
				}
				set
				{
					rowIndex = value;
				}
			}

			public bool EditingControlValueChanged
			{
				get
				{
					return valueChanged;
				}
				set
				{
					valueChanged = value;
				}
			}

			public bool EditingControlWantsInputKey(Keys keyData, bool dataGridViewWantsInputKey)
			{
				switch (keyData & Keys.KeyCode)
				{
					case Keys.Prior:
					case Keys.Next:
						return valueChanged;
					case Keys.Left:
					case Keys.Right:
					case Keys.Home:
					case Keys.End:
						return true;
					default:
						return !dataGridViewWantsInputKey;
				}
			}

			public Cursor EditingPanelCursor
			{
				get
				{
					return base.Cursor;
				}
			}

			public object GetEditingControlFormattedValue(DataGridViewDataErrorContexts context)
			{
				return _value = Controls[0].Text;
			}

			public void PrepareEditingControlForEdit(bool selectAll)
			{
				Initialize(selectAll);
			}

			public bool RepositionEditingControlOnValueChange
			{
				get
				{
					return false;
				}
			}
			#endregion
		}
		#endregion
	}
}
